=> 箭头函数


之前在学校里面写的项目很少会用到 ES6 ,就算是用也只不过是将 const 啊、let 啊或者是 set 这些简单地用一用,现在在公司看到的项目才发觉,大家早就熟练地用上了 ES6 的东西,最近也在学着使用,发现有些东西使用 ES6 的语法来写的确方便很多,下面就介绍一下箭头函数:

箭头函数一般比一个函数表达式更短,并且不绑定自己的 this、argumrnts、super 或 new.target,适用于非方法函数,并且它们不能用作构造函数。

基础语法:

  1. 参数、返回值

    1
    2
    3
    4
    5
    6
    7
    function(a) {
    return a+1;
    }

    //=>:

    a => a + 1;
  2. 参数、操作、无返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function(event) {
    test1();
    test2();
    }
    //=>
    event => {
    test1();
    test2();
    }
  3. 参数、操作、有返回值(不忽略 return)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function(x) {
    if( x > 0 ) {
    return x * x;
    }else {
    return x + x;
    }
    }
    //=>
    x=> {
    if( x > 0 ) {
    return x * x;
    }else {
    return x + x;
    }
    }
  4. 参数、返回值( {} 为函数体,可另外加括号表示返回值 )

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function(x) {
    return {
    foo: x
    };
    }
    //=>

    x => {
    foo: x
    }
  5. 多参数( 利用括号 )

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function(x,y,z,...rest) {
    var i ,sum = x+y;
    for( i = 0; r < rest.length; i++ ) {
    sum += rest[i];
    }
    return sam;
    }
    // =>
    ( x,y,z,...rest ) => {
    var i ,sum = x+y;
    for( i = 0; r < rest.length; i++ ) {
    sum += rest[i];
    }
    return sam;
    }

作用:
箭头函数的引用有两方面的作用:

  • 更简短的函数书写
  • 对 this 的词法解析

短函数书写这块我们在上面的例子已经领略过了,这里就不提了,这里来说说 对 this 的词法解析。

  1. 不绑定 this
    在箭头函数以前,每个新定义的函数都会有自己的 this 值,在面向对象风格的编程中,这会带来很多困扰。
    eg:
    1
    2
    3
    4
    5
    6
    7
    8
    function Person() {
    this.age = 0;
    serInterval(function growUp() {
    //在非严格模式下, groupUp() 函数定义了内部的 this 为 全局对象而非 Person 中的 this
    this.age ++;
    },3000);
    }
    var p = new Person();

(1)闭包解决

在 ECMAScript 对此的解决方法是通过 this 值赋给变量,将变量放到闭包中去解决。
1
2
3
4
5
6
7
8
function Person() {
var that = this;
that.age = 0;
setInterval(function growUp() {
that.age++;
});
}
var p = new Person();

(2)bind 函数解决

.bind(this)

(3) 箭头函数
而箭头函数解决了这个情景的问题,它会捕捉其所在的上下文的 this 值,来作为自己的 this 值,因此下面的代码捕捉到的是 Person 中的 this:

1
2
3
4
5
6
7
function Person() {
this.age = 0;
setInterval( () => {
this.age++;
},3000 )
}
var p = new Person();

另外:

<1> 箭头函数的写法会忽略严格模式中与 this 相关的规则

1
2
3
4
5
var f = () => {
'use strict';
return this;
};
f() === window; //true

<2> call() 与 apply() 方法传入的只是参数,不会影响 this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var adder = {
base: 1,
add : function(a) {
var f = v => v + this.base;
return f(a);
},
addThruCall: function(a) {
var f = v => v + this.base;
var b = {
base: 2,
};
return f.call(b, a);
},
}
console.log(adder.add(1)); // 2
console.log(adder.addThruCall(1));// 2

  • 不绑定参数

    箭头函数不会再内部暴露参数(arguments)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var arguments = 42;//若 => 所在作用域上无 arguments 则内部的 arguments 为 undefined

    var arr = () => arguments;
    arr();//42

    function foo() {
    console.log(arguments[0]);//5
    var f = (i) => arguments[0] + i;// 注意这里 arguments 取的是 foo 的参数,箭头函数是不会暴露内部参数的。
    return f(2);
    }
    foo(5); // 7

箭头函数没有自己的 arguments,不过大多数情况下,rest 参数可以给出一个解决方案:

1
2
3
4
5
function foo() {
var f = (...args) = args[0];
return f(2);
}
foo(1);// 2
  • 使用 new 操作符
    箭头函数不能用作构造器,否则会抛出错误

    1
    2
    var Foo = () => {};
    var foo = new Foo();// Uncaught TypeError: Foo is not a constructor
  • 使用原型属性
    箭头函数没有原型属性。

    1
    2
    var Foo = () => {};
    console.log(Foo.prototype);//undefined
  • 使用 yield 关键字
    yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。

补充:

  • 返回文字表达式
    用箭头函数返回一个文字表达式是行不通的。
    1
    2
    3
    4
    5
    6
    7
    8
    var func = () => {
    foo:1
    };
    //undefined
    var func = () => {
    foo: function() {};
    }
    // Uncaught SyntaxError: Unexpected token (

这是因为花括号(即 {} )里面的代码被解析为序列语句了(例如, foo 被认为是一个标签, 而非文字表达式的组成部分)。
所以,记得用圆括号把文字表达式包起来:

1
2
3
4
5
var func = () => (
{
foo: 1
}
);
  • 换行
    箭头函数在参数与箭头间不可换行:
1
2
3
    var func = ()
=> 1;
//Uncaught SyntaxError: Unexpected token =>
  • 解析顺序
    箭头函数的箭头虽然不是操作符也不是运算符,但是会受操作符优先级的影响
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let callback;

callback = callback || function() {};
// ok
callback = callback || () => {};
// SyntaxError:非法箭头函数属性
callback = callback || (() => {});
// ok

function foo() {
console.log(arguments[0]);//5
var f = (i) => arguments[0] + i;
return f(2);
}
foo(5); // 7